package com.csaba.swing.action;

import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.swing.AbstractAction;
import javax.swing.JOptionPane;
import javax.swing.KeyStroke;

import com.csaba.connector.BankServiceFactory;
import com.csaba.connector.ServiceException;
import com.csaba.connector.model.Account;
import com.csaba.connector.model.HistoryItem;
import com.csaba.connector.model.Session;
import com.csaba.connector.service.AccountHistoryService;
import com.csaba.swing.MainWindow;
import com.csaba.swing.gui.ContextListener;
import com.csaba.swing.gui.GUIContext;
import com.csaba.swing.gui.TransactionFilterDialog;
import com.csaba.swing.gui.TransactionListView;
import com.csaba.swing.gui.util.GUIUtil;
import com.csaba.swing.model.AccountCache;
import com.csaba.swing.model.TransactionFilter;
import com.csaba.util.LoggerHelper;

@SuppressWarnings( "serial" )
public class TransactionFilterAction extends AbstractAction implements ContextListener
{
	private final static Logger logger = LoggerHelper.getDefaultLogger();

	public TransactionFilterAction()
	{
		super(MainWindow.getString("TransactionFilterAction.menuItem")); //$NON-NLS-1$
		setEnabled(false);
		putValue(SMALL_ICON, GUIContext.getIcon("transactions", 16)); //$NON-NLS-1$
		putValue(LARGE_ICON_KEY, GUIContext.getIcon("transactions", 32)); //$NON-NLS-1$
		GUIUtil.setMnemonic(this);
		putValue(ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_F6, 0));
		GUIContext.getInstance().addContextListener(this);
	}

	@Override
	public void actionPerformed( final ActionEvent e )
	{
		final GUIContext context = GUIContext.getInstance();
		if ( !context.hasActiveSession() )
		{
			JOptionPane
					.showMessageDialog(
							MainWindow.getFrame(),
							MainWindow.getString("TransactionFilterAction.msg.noSession"), MainWindow.getString("TransactionFilterAction.titleError"), //$NON-NLS-1$ //$NON-NLS-2$
							JOptionPane.ERROR_MESSAGE);
			return;
		}

		final TransactionFilter filter = TransactionFilterDialog.getFilter(null);
		if ( filter == null )
			return;

		updateView(filter, null);
	}

	public void updateView( final TransactionFilter filter, TransactionListView view )
	{
		final GUIContext context = GUIContext.getInstance();

		final List<HistoryItem> itemList = new ArrayList<HistoryItem>();

		if ( filter.getAccount() != null )
		{
			//check whether the bank selection matches account selection
			if ( filter.getBank() == null || filter.getBank().equals(filter.getAccount().getBank()) )
			{
				final Session[] sessions = AccountCache.getInstace().getSession(filter.getAccount());
				if ( sessions != null && sessions.length > 0 )
				{
					addItems(sessions[0], filter, itemList);
				}
				else
				{
					logger.severe("Account missing from the cache: " + filter.getAccount()); //$NON-NLS-1$
				}
			}
		}
		else
		{ //download for more accounts
			final List<Session> sessions = context.getSessions();
			for ( final Session session : sessions )
			{
				if ( ( filter.getBank() != null && !filter.getBank().equals(session.getBank()) ) )
					continue;
				if ( filter.getCustomer() != null && !filter.getCustomer().equals(session.getCustomer()) )
					continue;

				final Account[] accounts = AccountCache.getInstace().get(session);
				for ( int i = 0; i < accounts.length; i++ )
				{
					//use the same filter object to iterate over the accounts
					filter.setAccount(accounts[i]);

					addItems(session, filter, itemList);
				}
			}
			//set back filter to its original state
			filter.setAccount(null);
		}

		if ( view == null )
		{
			view = new TransactionListView();
			MainWindow.getDesktop().add(view);
		}
		view.showIt(filter, itemList.toArray(new HistoryItem[0]));
	}

	private void addItems( final Session session, final TransactionFilter filter, final List<HistoryItem> itemList )
	{
		try
		{
			final AccountHistoryService service = BankServiceFactory.getBankService(session.getBank(),
					AccountHistoryService.class);
			service.setAccount(filter.getAccount());
			service.setDateRange((Date) filter.getFrom().clone(), (Date) filter.getTo().clone());

			( new ServiceRunner(session, service,
					MainWindow.getString("TransactionFilterAction.msg.getAccountHistory") + filter.getAccount()) ) //$NON-NLS-1$
					.execute();

			final HistoryItem[] items = service.getHistory();
			if ( items != null )
			{
				for ( int i = 0; i < items.length; i++ )
				{
					itemList.add(items[i]);
				}
			}
		}
		catch ( final ServiceException ex )
		{
			logger.log(Level.SEVERE, "Error loading transactions.", ex); //$NON-NLS-1$
			JOptionPane
					.showMessageDialog(
							MainWindow.getFrame(),
							MainWindow.getString("TransactionFilterAction.msg.historyError") + MainWindow.getString("TransactionFilterAction.eol") //$NON-NLS-1$ //$NON-NLS-2$
									+ ex.getMessage()
									+ MainWindow.getString("TransactionFilterAction.eol") + ex.getNativeMessage(), MainWindow.getString("TransactionFilterAction.titleError"), JOptionPane.ERROR_MESSAGE); //$NON-NLS-1$ //$NON-NLS-2$
		}
		catch ( final Exception ex )
		{
			logger.log(Level.SEVERE, "Error loading transactions.", ex); //$NON-NLS-1$
			JOptionPane
					.showMessageDialog(
							MainWindow.getFrame(),
							MainWindow.getString("TransactionFilterAction.msg.historyFatalError") + MainWindow.getString("TransactionFilterAction.eol") //$NON-NLS-1$ //$NON-NLS-2$
									+ ex.getMessage(),
							MainWindow.getString("TransactionFilterAction.titleFatalError"), JOptionPane.ERROR_MESSAGE); //$NON-NLS-1$
		}
	}

	@Override
	public void contextEventPerformed( final int eventType )
	{
		setEnabled(GUIContext.getInstance().hasActiveSession());
	}

}
